#include "ti_msp_dl_config.h"
#include "FreeRTOS.h"
#include "task.h"

/**
 * @brief 系统状态枚举
 *
 * 定义系统可能处于的各种状态
 */
typedef enum {
    SYS_IDLE,           //!< 空闲状态
    SYS_BLINK_SLOW,     //!< 慢闪烁(1Hz)
    SYS_BLINK_FAST,     //!< 快闪烁(5Hz)
    SYS_LED_ON,         //!< LED常亮
    SYS_LED_OFF,        //!< LED常灭
    SYS_STATE_MAX       //!< 状态数量最大值
} SystemState;

/**
 * @brief 系统事件枚举
 *
 * 定义系统可能检测到的各种事件
 */
typedef enum {
    EVT_NONE,           //!< 无事件
    EVT_BTN_PRESS,      //!< 按钮按下(<1s)
    EVT_BTN_HOLD,       //!< 按钮长按(=3s)
    EVT_BTN_RELEASE,    //!< 按钮释放
    EVT_MAX             //!< 事件数量最大值
} SystemEvent;

/**
 * @brief 按钮状态枚举
 *
 * 定义按钮的两种基本状态
 */
typedef enum {
    BTN_RELEASED,       //!< 按钮释放状态
    BTN_PRESSED         //!< 按钮按下状态
} ButtonState;

/**
 * @brief 状态处理函数指针类型
 *
 * 定义指向状态处理函数的函数指针类型
 */
typedef void (*StateHandler)(void);

/**
 * @brief 当前系统状态变量
 *
 * 记录系统当前所处的状态
 */
static SystemState currentState = SYS_LED_OFF;

/**
 * @brief 闪烁计数器
 *
 * 用于控制LED闪烁频率的计数器
 */
static uint32_t blinkCounter = 0;

/**
 * @brief 按键按下持续时间
 *
 * 记录按键按下的持续时间(毫秒)
 */
static uint32_t pressDuration = 0;

/**
 * @brief 空闲状态处理函数
 *
 * 处理系统处于空闲状态时的逻辑，实现LED呼吸灯效果
 */
static void Handle_Idle(void);

/**
 * @brief 慢闪烁状态处理函数
 *
 * 处理系统处于慢闪烁状态时的逻辑，实现1Hz频率闪烁
 */
static void Handle_BlinkSlow(void);

/**
 * @brief 快闪烁状态处理函数
 *
 * 处理系统处于快闪烁状态时的逻辑，实现5Hz频率闪烁
 */
static void Handle_BlinkFast(void);

/**
 * @brief LED常亮状态处理函数
 *
 * 处理系统处于LED常亮状态时的逻辑
 */
static void Handle_LedOn(void);

/**
 * @brief LED常灭状态处理函数
 *
 * 处理系统处于LED常灭状态时的逻辑
 */
static void Handle_LedOff(void);

/**
 * @brief 状态处理函数指针数组
 *
 * 存储各个状态对应的处理函数指针
 */
const StateHandler stateHandlers[SYS_STATE_MAX] = {
    Handle_Idle,        //!< SYS_IDLE状态处理函数
    Handle_BlinkSlow,   //!< SYS_BLINK_SLOW状态处理函数
    Handle_BlinkFast,   //!< SYS_BLINK_FAST状态处理函数
    Handle_LedOn,       //!< SYS_LED_ON状态处理函数
    Handle_LedOff       //!< SYS_LED_OFF状态处理函数
};

/**
 * @brief 获取系统事件函数
 *
 * 检测并返回当前发生的系统事件
 * @return SystemEvent 系统事件类型
 */
static SystemEvent GetSystemEvent(void);

/**
 * @brief 处理按钮事件函数
 *
 * 根据检测到的按钮事件更新系统状态
 */
static void ProcessButton(void);

/**
 * @brief 毫秒延时函数
 *
 * 通过循环实现精确的毫秒级延时
 * @param ms 延时毫秒数
 */
void delay_ms(uint32_t ms) {
    for(uint32_t i = 0; i < ms; i++) {
        for(uint32_t j = 0; j < (CPUCLK_FREQ/1000)/3; j++) {
            __asm__("nop");
        }
    }
}

/******************** 状态处理函数实现 ********************/

/**
 * @brief 空闲状态处理函数实现
 *
 * 实现LED呼吸灯效果，亮度逐渐增强后逐渐减弱
 */
void Handle_Idle(void) {
    // 控制LED亮度变化方向
    static uint8_t direction = 0;
    static uint16_t brightness = 0;

    if(direction == 0) {
        if(++brightness >= 1000) direction = 1;
    } else {
        if(--brightness == 0) direction = 0;
    }

    // 通过PWM控制LED亮度
    for(uint16_t i = 0; i < 1000; i++) {
        if(i < brightness) {
            DL_GPIO_setPins(LED1_PORT, LED1_PIN_2_PIN);
        } else {
            DL_GPIO_clearPins(LED1_PORT, LED1_PIN_2_PIN);
        }
        vTaskDelay(1);
    }
}

/**
 * @brief 慢闪烁状态处理函数实现
 *
 * 实现1Hz频率的LED闪烁效果(500ms亮,500ms灭)
 */
void Handle_BlinkSlow(void) {
    blinkCounter++;
    if(blinkCounter == 200) {
        DL_GPIO_setPins(LED1_PORT, LED1_PIN_2_PIN);
    } else if(blinkCounter >= 1000) {
        DL_GPIO_clearPins(LED1_PORT, LED1_PIN_2_PIN);
        blinkCounter = 0;
    }
}

/**
 * @brief 快闪烁状态处理函数实现
 *
 * 实现5Hz频率的LED闪烁效果(100ms亮,100ms灭)
 */
void Handle_BlinkFast(void) {
    blinkCounter++;
    if(blinkCounter == 100) {
        DL_GPIO_setPins(LED1_PORT, LED1_PIN_2_PIN);
    } else if(blinkCounter >= 200) {
        DL_GPIO_clearPins(LED1_PORT, LED1_PIN_2_PIN);
        blinkCounter = 0;
    }
}

/**
 * @brief LED常亮状态处理函数实现
 *
 * 保持LED常亮状态
 */
void Handle_LedOn(void) {
    DL_GPIO_clearPins(LED1_PORT, LED1_PIN_2_PIN);
}

/**
 * @brief LED常灭状态处理函数实现
 *
 * 保持LED常灭状态
 */
void Handle_LedOff(void) {
    DL_GPIO_setPins(LED1_PORT, LED1_PIN_2_PIN);
}

/******************** 事件处理函数实现 ********************/

/**
 * @brief 获取系统事件函数实现
 *
 * 检测按钮状态并判断是否产生相应事件
 * @return SystemEvent 检测到的系统事件
 */
SystemEvent GetSystemEvent(void) {
    static ButtonState btnState = BTN_RELEASED;
    static uint32_t pressStartTime = 0;
    SystemEvent event = EVT_NONE;

    if(DL_GPIO_readPins(KEY_PORT, KEY_PIN_18_PIN)) {
        if(btnState == BTN_RELEASED) {
            btnState = BTN_PRESSED;
            pressStartTime = pressDuration;
        }
        pressDuration++;

        // 检测长按事件(3秒)
        if(pressDuration - pressStartTime >= 3000) {
            event = EVT_BTN_HOLD;
        }
    } else {
        if(btnState == BTN_PRESSED) {
            btnState = BTN_RELEASED;
            // 检测短按事件
            if(pressDuration - pressStartTime < 3000) {
                event = EVT_BTN_PRESS;
            }
            pressStartTime = 0;
        }
        pressDuration = 0;
    }

    return event;
}

/**
 * @brief 处理按钮事件函数实现
 *
 * 根据当前状态和检测到的事件更新系统状态
 */
void ProcessButton(void) {
    SystemEvent event = GetSystemEvent();

    // 根据当前状态和事件进行状态转换
    switch(currentState) {
        case SYS_LED_OFF:
            if(event == EVT_BTN_PRESS) currentState = SYS_BLINK_SLOW;
            break;

        case SYS_BLINK_SLOW:
            if(event == EVT_BTN_PRESS) currentState = SYS_BLINK_FAST;
            if(event == EVT_BTN_HOLD) currentState = SYS_LED_ON;
            break;

        case SYS_BLINK_FAST:
            if(event == EVT_BTN_PRESS) currentState = SYS_LED_OFF;
            if(event == EVT_BTN_HOLD) currentState = SYS_LED_ON;
            break;

        case SYS_LED_ON:
            if(event == EVT_BTN_PRESS) currentState = SYS_LED_OFF;
            break;

        default:
            currentState = SYS_LED_OFF;
    }
}

void Main_Task(void *pvParameters) {
    while(1) {
        // 1. 处理按钮事件
        ProcessButton();

        // 2. 执行当前状态对应的处理函数
        if(currentState < SYS_STATE_MAX) {
            stateHandlers[currentState]();
        }

        // 3. 延时1ms
        // vTaskDelay(1);
        vTaskDelay(1);
        // 4. 更新按键按下持续时间(每1ms加1)
        if(DL_GPIO_readPins(KEY_PORT, KEY_PIN_18_PIN)) {
            pressDuration++;
        }
    }
}


/******************** 主函数 ********************/

/**
 * @brief 主函数
 *
 * 系统入口点，初始化硬件并执行主循环
 * @return int 返回状态码(嵌入式系统中通常不返回)
 */
int main(void) {
    // 初始化系统配置
    SYSCFG_DL_init();

    // 初始化LED状态为关闭
    Handle_LedOff();
    xTaskCreate(Main_Task, "Main_Thread", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    vTaskStartScheduler(); // 启动调度器

}


static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];

void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
    /* 栈溢出时的处理代码 */
    /* 例如，打印错误信息并重置系统 */

    /* 参数:
     * xTask - 发生栈溢出的任务句柄
     * pcTaskName - 发生栈溢出的任务名称
     */

    /* 通常在这里添加一些错误处理和系统恢复的代码 */
    while(1) {

        /* 可以在此处添加错误处理代码，如闪烁LED或输出调试信息 */
    }
}

void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                  StackType_t **ppxIdleTaskStackBuffer,
                                  uint32_t *pulIdleTaskStackSize)
{
    /* 传递静态分配的空闲任务数据结构的地址 */
    *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;

    /* 传递静态分配的空闲任务堆栈的地址 */
    *ppxIdleTaskStackBuffer = uxIdleTaskStack;

    /* 传递堆栈大小 */
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}


/* 为定时器任务定义静态内存 */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];

void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                   StackType_t **ppxTimerTaskStackBuffer,
                                   uint32_t *pulTimerTaskStackSize)
{
    /* 传递静态分配的定时器任务数据结构的地址 */
    *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;

    /* 传递静态分配的定时器任务堆栈的地址 */
    *ppxTimerTaskStackBuffer = uxTimerTaskStack;

    /* 传递堆栈大小 */
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}